package com.dubito.gallery.ui.settings

import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.viewmodel.compose.viewModel
import com.dubito.gallery.BuildConfig
import com.dubito.gallery.LocalNavController
import com.dubito.gallery.R
import com.dubito.gallery.data.ColorThemeSettings
import com.dubito.gallery.data.DarkThemeSettings
import com.dubito.gallery.util.findActivity
import com.google.accompanist.systemuicontroller.rememberSystemUiController

private const val URL_PRIVACY_POLICY = "https://gitee.com/lianghy"

@Composable
fun SettingsScreen(viewModel: SettingsViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsState()
    SettingsContent(
        uiState = uiState,
        onChangeDarkTheme = { darkTheme -> viewModel.setDarkTheme(darkTheme = darkTheme) },
        onChangeColorTheme = { colorTheme -> viewModel.setColorTheme(colorTheme = colorTheme) },
        onChangeTapCountToOpenSettings = { tapCount -> viewModel.setTapCountOpenSettings(tapCount = tapCount) },
        onChangeMultiGoBack = { multiGoBack -> viewModel.setMultiGoBack(multiGoBack = multiGoBack) }
    )
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsContent(
    uiState: SettingsUiState,
    onChangeDarkTheme: (DarkThemeSettings) -> Unit,
    onChangeColorTheme: (ColorThemeSettings) -> Unit,
    onChangeTapCountToOpenSettings: (Int) -> Unit,
    onChangeMultiGoBack: (Int) -> Unit,
) {
    val topAppBarState = rememberTopAppBarState()
    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState)

    val scrollFraction by remember {
        derivedStateOf {
            topAppBarState.overlappedFraction
        }
    }
    val statusBarColor = TopAppBarDefaults.centerAlignedTopAppBarColors()
        .containerColor(colorTransitionFraction = scrollFraction).value
    val systemUiController = rememberSystemUiController()

    SideEffect {
        systemUiController.setStatusBarColor(statusBarColor)
    }

    Scaffold(
        modifier = Modifier
            .nestedScroll(scrollBehavior.nestedScrollConnection)
            .safeDrawingPadding(),
        topBar = {
            val navController = LocalNavController.current
            SmallTopAppBar(
                title = { Text(text = stringResource(id = R.string.settings)) },
                scrollBehavior = scrollBehavior,
                navigationIcon = {
                    IconButton(onClick = { navController.navigateUp() }) {
                        Icon(
                            imageVector = Icons.Default.ArrowBack,
                            contentDescription = stringResource(id = R.string.desc_back)
                        )
                    }
                }
            )
        }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) {
            if (uiState is SettingsUiState.Success) {
                SettingsList(
                    darkTheme = uiState.darkTheme,
                    onChangeDarkTheme = onChangeDarkTheme,
                    colorTheme = uiState.colorTheme,
                    onChangeColorTheme = onChangeColorTheme,
                    tapCountToOpenSettings = uiState.tapCountToOpenSettings,
                    onChangeTapCountToOpenSettings = onChangeTapCountToOpenSettings,
                    multiGoBack = uiState.multiGoBack,
                    onChangeMultiGoBack = onChangeMultiGoBack
                )
            }
        }
    }
}

@Composable
fun SettingsList(
    darkTheme: DarkThemeSettings,
    onChangeDarkTheme: (DarkThemeSettings) -> Unit,
    colorTheme: ColorThemeSettings,
    onChangeColorTheme: (ColorThemeSettings) -> Unit,
    tapCountToOpenSettings: Int,
    onChangeTapCountToOpenSettings: (Int) -> Unit,
    multiGoBack: Int,
    onChangeMultiGoBack: (Int) -> Unit
) {
    LazyColumn(modifier = Modifier.fillMaxWidth()) {
        item { SettingsHeader(title = stringResource(id = R.string.setting_header_display)) }
        item { SettingCellFolder() }

        item { SettingsHeader(title = stringResource(id = R.string.setting_header_childproof)) }
        item {
            SettingCellTapCountToOpenSettings(
                tapCountToOpenSettings = tapCountToOpenSettings,
                onChangeTapCountToOpenSettings = onChangeTapCountToOpenSettings
            )
        }
        item {
            SettingsCellMultiGoBack(
                multiGoBack = multiGoBack,
                onChangeMultiGoBack = onChangeMultiGoBack
            )
        }

        item { SettingsHeader(title = stringResource(id = R.string.setting_header_theme)) }
        item {
            SettingsCellDarkTheme(
                darkTheme = darkTheme,
                onChangeDarkTheme = onChangeDarkTheme
            )
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            item {
                SettingsCellColorTheme(
                    colorTheme = colorTheme,
                    onChangeColorTheme = onChangeColorTheme
                )
            }
        }

        item { SettingsHeader(title = stringResource(id = R.string.setting_header_about)) }
        item { SettingsCellVersion() }
        item { SettingsPrivacyPolicy() }
    }
}

@Composable
fun SettingsCellVersion() {
    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_version),
        value = BuildConfig.VERSION_NAME
    )
}

@Composable
fun SettingsPrivacyPolicy() {
    val activity = LocalContext.current.findActivity()
    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_privacy_policy),
        value = stringResource(id = R.string.setting_value_open_in_browser),
        modifier = Modifier.clickable {
            val webIntent = Intent(Intent.ACTION_VIEW, Uri.parse(URL_PRIVACY_POLICY))
            activity.startActivity(webIntent)
        }
    )
}

@Composable
fun SettingsCellColorTheme(
    colorTheme: ColorThemeSettings,
    onChangeColorTheme: (ColorThemeSettings) -> Unit
) {
    val current = colorTheme.toInt()
    var showDialog by remember { mutableStateOf(false) }

    val options = listOf(
        stringResource(id = R.string.setting_value_app_colors),
        stringResource(id = R.string.setting_value_use_wallpaper_colors)
    )
    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_colortheme),
        value = options[current],
        modifier = Modifier.clickable { showDialog = true }
    )

    if (showDialog) {
        RadioButtonDialog(
            title = stringResource(id = R.string.setting_title_colortheme),
            options = options,
            selected = current,
            onSelect = { selected ->
                onChangeColorTheme(ColorThemeSettings.fromInt(selected))
                showDialog = false
            }
        )
    }
}

@Composable
fun SettingsCellDarkTheme(
    darkTheme: DarkThemeSettings,
    onChangeDarkTheme: (DarkThemeSettings) -> Unit
) {
    val current = darkTheme.toInt()
    var showDialog by remember { mutableStateOf(false) }

    val options = listOf(
        stringResource(id = R.string.setting_value_off),
        stringResource(id = R.string.setting_value_on),
        stringResource(id = R.string.setting_value_use_system_settings),
    )

    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_darktheme),
        value = options[current],
        modifier = Modifier.clickable { showDialog = true }
    )

    if (showDialog) {
        RadioButtonDialog(
            title = stringResource(id = R.string.setting_title_darktheme),
            options = options,
            selected = current,
            onSelect = { selected ->
                onChangeDarkTheme(DarkThemeSettings.fromInt(selected))
                showDialog = false
            }
        )
    }
}

/**
 * 返回
 */
@Composable
fun SettingsCellMultiGoBack(
    multiGoBack: Int,
    onChangeMultiGoBack: (Int) -> Unit
) {
    var showDialog by remember { mutableStateOf(false) }
    val options = listOf(
        stringResource(id = R.string.setting_value_multi_go_back_1),
        stringResource(id = R.string.setting_value_multi_go_back_2),
        stringResource(id = R.string.setting_value_multi_go_back_3),
        stringResource(id = R.string.setting_value_multi_go_back_4),
        stringResource(id = R.string.setting_value_multi_go_back_5),
    )

    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_multi_go_back),
        value = options[multiGoBack - 1],
        modifier = Modifier.clickable { showDialog = true }
    )

    if (showDialog) {
        RadioButtonDialog(
            title = stringResource(id = R.string.setting_title_multi_go_back),
            text = stringResource(id = R.string.setting_desc_multi_go_back),
            options = options,
            selected = multiGoBack - 1,
            onSelect = { selected ->
                if (selected != options.size) {
                    onChangeMultiGoBack(selected + 1)
                }
                showDialog = false
            }
        )
    }

}

/**
 * 打开设置
 */
@Composable
fun SettingCellTapCountToOpenSettings(
    tapCountToOpenSettings: Int,
    onChangeTapCountToOpenSettings: (Int) -> Unit
) {
    var showDialog by remember { mutableStateOf(false) }
    val options = listOf(
        stringResource(id = R.string.setting_value_tap_count_to_open_settings_1),
        stringResource(id = R.string.setting_value_tap_count_to_open_settings_2),
        stringResource(id = R.string.setting_value_tap_count_to_open_settings_3),
        stringResource(id = R.string.setting_value_tap_count_to_open_settings_4),
        stringResource(id = R.string.setting_value_tap_count_to_open_settings_5)
    )

    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_tap_count_to_open_settings),
        value = options[tapCountToOpenSettings - 1],
        modifier = Modifier.clickable { showDialog = true }
    )

    if (showDialog) {
        RadioButtonDialog(
            title = stringResource(id = R.string.setting_title_tap_count_to_open_settings),
            text = stringResource(id = R.string.setting_desc_tap_count_to_open_settings),
            options = options,
            selected = tapCountToOpenSettings - 1,
            onSelect = { selected ->
                if (selected != options.size) {
                    onChangeTapCountToOpenSettings(selected + 1)
                }
                showDialog = false
            }
        )
    }
}

@Composable
fun SettingCellFolder() {
    val navController = LocalNavController.current
    SettingsItemCell(
        title = stringResource(id = R.string.setting_title_folder),
        value = stringResource(id = R.string.setting_desc_folder),
        modifier = Modifier.clickable { navController.navigate("settings_folder") }
    )
}


@Composable
fun SettingsItemCell(
    title: String,
    value: String,
    modifier: Modifier = Modifier
) {
    Surface(color = MaterialTheme.colorScheme.surface, modifier = modifier.fillMaxWidth()) {
        Column {
            Text(
                text = title,
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier.padding(
                    start = SettingsScreenTokens.ItemPaddingStart,
                    top = SettingsScreenTokens.ItemPaddingVertical
                )
            )
            Text(
                text = value,
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.outline,
                modifier = Modifier.padding(
                    start = SettingsScreenTokens.ItemPaddingStart,
                    top = SettingsScreenTokens.ItemPaddingVertical
                )
            )
            Divider(color = MaterialTheme.colorScheme.outline, thickness = Dp.Hairline)
        }
    }
}

@Composable
fun SettingsHeader(title: String) {
    Surface(color = MaterialTheme.colorScheme.surface) {
        Box(
            modifier = Modifier.padding(
                start = SettingsScreenTokens.ItemPaddingStart,
                top = SettingsScreenTokens.HeaderPaddingTop
            )
        ) {
            Text(
                text = title,
                style = MaterialTheme.typography.titleLarge,
                color = MaterialTheme.colorScheme.tertiary
            )
        }
    }
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun RadioButtonDialog(
    title: String,
    text: String = "",
    options: List<String>,
    selected: Int,
    onSelect: (Int) -> Unit
) {
    AlertDialog(
        onDismissRequest = { onSelect(selected) },
        confirmButton = {},
        modifier = Modifier.fillMaxWidth(0.9f),
        title = {
            Text(text = title, style = MaterialTheme.typography.titleLarge)
        },
        text = {
            Column(
                modifier = Modifier
                    .selectableGroup()
                    .verticalScroll(rememberScrollState())
            ) {
                Text(text = text)
                options.forEachIndexed { index, option ->
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(56.dp)
                            .selectable(
                                selected = (index == selected),
                                onClick = {
                                    onSelect(index)
                                },
                                role = Role.RadioButton
                            ),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        RadioButton(selected = (index == selected), onClick = null)
                        Text(
                            text = option,
                            style = MaterialTheme.typography.titleMedium,
                            modifier = Modifier.padding(start = 16.dp)
                        )
                    }
                }
            }
        },
        properties = DialogProperties(usePlatformDefaultWidth = false)
    )
}